package org.myorg;

import java.util.Random;

public class FEvolution {
	/*
	 * 
	 * @param p_s 选择算子
	 * @param p_c 交叉算子 
	 * @param p_m 变异算子
	 */
	private double ps;
	private double pc;
	private double pm;
	private FPeople people;
	private Fc fun;

	public FEvolution(double p_s, double p_c, double p_m, FPeople p, Fc fun) {
		ps = p_s;
		pc = p_c;
		pm = p_m;
		people = p;
		this.fun = fun;
	}

	/*
	 * 使用锦标赛的选择算法
	 */
	public void select() {
		for (int i = 0; i < people.p_num; i++) {
			if (i == 0 || i == 1) {
				people.getPersons()[i] = new FGene(people.getPersons()[people.getBest(fun)]);
			} else {
				int pos1 = (int) (Math.random()*people.p_num);
				int pos2 = (int) (Math.random()*people.p_num);
				if (fun.better(people.getPersons()[pos1],people.getPersons()[pos2]))
					people.getPersons()[i] = new FGene(people.getPersons()[pos1]);
				else
					people.getPersons()[i] = new FGene(people.getPersons()[pos2]);	
			}

		}
	}

	public void select(FPeople p) {
		for (int i = 0; i < people.p_num; i++) {
			if (i==0 || i==1) {
				people.getPersons()[i] = new FGene(p.getPersons()[p.getBest(fun)]);
			} else if (i == 2 || i == 3) {
				people.getPersons()[i] = new FGene(people.getPersons()[people.getBest(fun)]);
			} else {
				int pos1 = (int) (Math.random()*people.p_num);
				int pos2 = (int) (Math.random()*people.p_num);
				if (fun.better(people.getPersons()[pos1],people.getPersons()[pos2]))
					people.getPersons()[i] = new FGene(people.getPersons()[pos1]);
				else
					people.getPersons()[i] = new FGene(people.getPersons()[pos2]);	
			}

		}
	}


	/*
	 * 平坦交叉
	 */
	public void crossOver() {
		for (int i=0; i < (int) (pc*people.p_num); i++) {
			int pos1 = (int) (Math.random()*people.p_num);
			int pos2 = (int) (Math.random()*people.p_num);

			for (int j=0; j < people.getPersons()[0].getLength(); j++){
				if (Math.random() > 0.5) {
					double temp = people.getPersons()[pos1].geneAt(j);
					people.getPersons()[pos1].setGene(j, 
							people.getPersons()[pos2].geneAt(j));
					people.getPersons()[pos2].setGene(j, temp);
				}
			}
		}
	}

	/*
	 * 高斯变异
	 */
	public void mutation() {
		Random r = new Random();
		int gene_l = people.getPersons()[0].length;

		for(int i = 0; i < (int) (pm*people.p_num); i++) {
			//TODO add the number of mutation
			int pos = (int) (Math.random()*people.p_num);

			for (int j = 0; j < gene_l; j++) {
				//int mut_pos = (int) (Math.random()*people.getPersons()[pos].length);
				double temp = people.getPersons()[pos].geneAt(j);
				double high = people.getPersons()[pos].high[j];
				double low = people.getPersons()[pos].low[j];
				double dis = high - low;

				double rand = r.nextGaussian();
				double test = rand*dis*0.1;
				double test2 = Math.min(high, temp + rand*dis*0.1);
				temp = Math.max(Math.min(high, temp + rand*dis*0.1),low); 

				//temp = 3.14*Math.random();

				people.getPersons()[pos].setGene(j, temp);
			}

		}
	}
}
